import { httpError, Inject, Provide } from '@midwayjs/core'
import { Context } from '@midwayjs/koa'
import { InjectEntityModel } from '@midwayjs/typeorm'
import { Repository } from 'typeorm'

import { DeleteDTO } from '@/dto'
import { SysDictDataEntity, SysDictTypeEntity } from '@/entity'
import { StateService } from '@/service'

import {
  CreateDictDataDTO,
  CreateDictTypeDTO,
  FindDictDataPageDTO,
  FindDictTypePageDTO,
  UpdateDictDataDTO,
  UpdateDictTypeDTO
} from './dict.dto'

@Provide()
export class DictService {
  @Inject()
  ctx: Context

  @InjectEntityModel(SysDictTypeEntity)
  dictTypeModel: Repository<SysDictTypeEntity>

  @InjectEntityModel(SysDictDataEntity)
  dictDataModel: Repository<SysDictDataEntity>

  async handleCreateDictType(dto: CreateDictTypeDTO) {
    const stateService = await this.ctx.requestContext.getAsync(StateService)

    const jwtPayload = stateService.getJwtPayload()

    const oldDictType = await this.dictTypeModel.findOne({
      where: { dictType: dto.dictType }
    })

    if (oldDictType) {
      this.ctx.throw(new httpError.BadRequestError('字典类型已存在'))
    }

    const newDictType = new SysDictTypeEntity()

    Object.assign<any, any, Partial<SysDictTypeEntity>>(newDictType, dto, {
      createBy: jwtPayload.userName
    })

    await this.dictTypeModel.save(newDictType)
  }

  async handleDeleteDictType(dto: DeleteDTO) {
    const { ids } = dto

    await this.dictTypeModel.delete(ids)
  }

  async handleUpdateDictType(id: string, dto: UpdateDictTypeDTO) {
    const stateService = await this.ctx.requestContext.getAsync(StateService)

    const jwtPayload = stateService.getJwtPayload()

    const oldDictType = await this.dictTypeModel.findOne({
      where: { dictId: id }
    })

    if (!oldDictType) {
      this.ctx.throw(new httpError.BadRequestError('字典类型不存在'))
    }

    Object.assign<any, any, Partial<SysDictTypeEntity>>(oldDictType, dto, {
      updateBy: jwtPayload.userName
    })

    await this.dictTypeModel.save(oldDictType)
  }

  async handleFindDictType(id: string) {
    return await this.dictTypeModel.findOne({
      where: { dictId: id }
    })
  }

  async handleFindDictTypePage(dto: FindDictTypePageDTO) {
    const { pageNum, pageSize, ...where } = dto

    const [list, total] = await this.dictTypeModel.findAndCount({
      where: {
        ...where
      },
      take: pageSize,
      skip: (pageNum - 1) * pageSize
    })

    return {
      pageNum,
      pageSize,
      total,
      list
    }
  }

  async handleFindDictDataPage(dto: FindDictDataPageDTO) {
    const { pageNum, pageSize, ...where } = dto

    const [list, total] = await this.dictDataModel.findAndCount({
      where: {
        ...where
      },
      order: {
        dictSort: 'ASC'
      },
      take: pageSize,
      skip: (pageNum - 1) * pageSize
    })

    return {
      pageNum,
      pageSize,
      total,
      list
    }
  }

  async handleFindDictDataList(dictType: string) {
    return await this.dictDataModel.find({ where: { dictType, status: '0' } })
  }

  async handleCreateDictData(dto: CreateDictDataDTO) {
    const stateService = await this.ctx.requestContext.getAsync(StateService)

    const jwtPayload = stateService.getJwtPayload()
    const dictData = new SysDictDataEntity()

    Object.assign<any, any, Partial<SysDictDataEntity>>(dictData, dto, {
      createBy: jwtPayload.userName
    })

    await this.dictDataModel.save(dictData)
  }

  async handleUpdateDictData(id: string, dto: UpdateDictDataDTO) {
    const stateService = await this.ctx.requestContext.getAsync(StateService)

    const jwtPayload = stateService.getJwtPayload()

    const oldDictData = await this.dictDataModel.findOne({
      where: { dictCode: id }
    })

    if (!oldDictData) {
      this.ctx.throw(new httpError.BadRequestError('字典数据不存在'))
    }

    Object.assign<any, any, Partial<SysDictDataEntity>>(oldDictData, dto, {
      updateBy: jwtPayload.userName
    })

    await this.dictDataModel.save(oldDictData)
  }

  async handleDeleteDictData(dto: DeleteDTO) {
    const { ids } = dto

    await this.dictDataModel.delete(ids)
  }
}
